

public class Tetro {
	
	public static final int NB_TETROS = 7;
	public static final int ID_NONE = 0;
	public static final int ID_FIRST = 1;
	public static final int ID_T = 1;
	public static final int ID_S = 2;
	public static final int ID_Z = 3;
	public static final int ID_L = 4;
	public static final int ID_J = 5;
	public static final int ID_I = 6;
	public static final int ID_O = 7;
	public static final int ID_LAST = 7;
	public static final byte TETROS[][][] = {
		//SRS rotation system
		//4 rotations for each tetros
		//3x3 and 4x4 blocks
		{//T shape
			{0,1,0},
			{1,1,1},
			{0,0,0}
		},{//S shape
			{0,1,1},
			{1,1,0},
			{0,0,0}
		},{//Z shape
			{1,1,0},
			{0,1,1},
			{0,0,0}
		},{//L shape
			{0,0,1},
			{1,1,1},
			{0,0,0}
		},{//J shape
			{1,0,0},
			{1,1,1},
			{0,0,0}
		},{//I shape
			{0,0,0,0},
			{1,1,1,1},
			{0,0,0,0},
			{0,0,0,0}
		},{//O shape
			{0,0,0,0},
			{0,1,1,0},
			{0,1,1,0},
			{0,0,0,0}
		}
	};
	
	
	public static final int CW = 1;
	public static final int CCW = -1;
	

	
	private int id;
	private int rotation; //[-3;3] always modulo 4, negative means counter clockwise
	private byte[][] matrix; //representation of the current shape rotated (3x3 or 4x4)
	
	// effective origin and width, height of the matrix
	// when a tetro doesn't fill it's entire matrix
	// i.e.: (1,1,3,3) for the O shape ; (0,1,4,2) for the I shape
	private int left;
	private int top;
	private int right;
	private int bottom;
	
	public Tetro(int id, int rot) {
		this.id = id;
		this.rotation = 0;
		this.matrix = TETROS[id-1];
		rotate(rot);
	}
	
	public Tetro(int id) {
		this(id, 0);
	}


	public void rotate(int direction) {
		int s = matrix.length;
		rotation = (rotation + direction) % 4;
		if (rotation == 0) {
			matrix = TETROS[id-1];
		} else {
			direction = direction % 4;
			for (int t=0 ; t < Math.abs(direction) ; t++){
				byte[][] temp = matrix;
				matrix = new byte[matrix.length][matrix.length];
				for (int i=0 ; i<s ; i++){
					for (int j=0 ; j<s ; j++){
						if (direction > 0) {
							//clockwise
							matrix[j][s-1-i] = temp[i][j];
						}else{
							//counter clockwise
							matrix[s-1-j][i] = temp[i][j];
						}
					}
				}
			}
		}
		left = calcLeft();
		right = calcRight();
		top = calcTop();
		bottom = calcBottom();
	}
	
	private int calcLeft() {
		//returns the effective left origin of a tetro matrix
		// i.e. returns 1 if the first column of a tetro is unoccupied
		int l=0;
		while (l < matrix.length){
			for (int i = 0 ; i < matrix.length ; i++) {
				if (matrix[l][i] > 0) {
					// any occupied cell on the column				
					return l;					
				}
			}
			l++;
		}
		return l;
	}
	
	private int calcRight() {
		//returns the effective right end (exclusive) of a tetro matrix
		// i.e. returns 3 for the O shape
		int r = matrix.length - 1;
		while (r >= 0) {
			for (int i = 0 ; i < matrix.length ; i++) {
				if (matrix[r][i] > 0) {
					// any occupied cell on the column				
					return r+1;
				}
			}
			r--;
		}
		return r+1;
	}
	
	private int calcTop() {
		//returns the effective top
		int t = 0;
		while (t < matrix.length){
			for (int i = 0 ; i < matrix.length ; i++) {
				if (matrix[i][t] > 0) {
					// any occupied cell on the row			
					return t;					
				}
			}
			t++;
		}
		return t;
	}
	
	private int calcBottom() {
		//returns the effective bottom (exclusive) of a tetro matrix
		// i.e. returns 3 for the O shape
		int b = matrix.length - 1;
		while (b >= 0) {
			for (int i = 0 ; i < matrix.length ; i++) {
				if (matrix[i][b] > 0) {
					// any occupied cell on the row			
					return b+1;
				}
			}
			b--;
		}
		return b+1;
	}
	
	public int getId() {
		return id;
	}

	public int getRotation() {
		return rotation;
	}

	public byte[][] getMatrix() {
		return matrix;
	}
	
	public int getLeft() {
		return left;
	}

	public int getTop() {
		return top;
	}

	public int getRight() {
		return right;
	}

	public int getBottom() {
		return bottom;
	}

	@Override
	public String toString() {
		String s = "Tetro [id=" + id + ", rotation=" + rotation + ", matrix=";
		for (int i=0 ; i<matrix.length ; i++){
			s = s + "\n";
			for (int j=0 ; j<matrix.length ; j++){
				s = s + matrix[i][j];
			}
		}
		return s + "]";
	}

	public static void main(String[] args) {
		Tetro t = new Tetro(1);
		for (int i=0 ; i<4 ; i++){
			System.out.println(t);
			t.rotate(CCW);
		}
		t.rotate(2);
		System.out.println(t);
		
	}
	
	
}





